home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "global.h"
- #include "timer.h"
- #include "proc.h"
- #include "mbuf.h"
- #include "commands.h"
- #include "daemon.h"
- #include "hardware.h"
- #include "socket.h"
-
- /* Head of running timer chain.
- * The list of running timers is sorted in increasing order of expiration;
- * i.e., the first timer to expire is always at the head of the list.
- */
- #ifdef MDEBUG
- struct timer *Timers; /* also used in alloc.c */
- #else
- static struct timer *Timers;
- #endif
-
- static void t_alarm __ARGS((void *x));
-
- /* Process that handles clock ticks */
- void
- timerproc(int i,void *v1,void *v2)
- {
- struct timer *t, *p, *expired;
- int i_state;
- void (**vf)();
-
- for(;;){
- i_state = dirps(); /* Tick is modified by an interrupt */
-
- while(Tick == 0)
- pwait(&Tick);
-
- Tick = 0; /* */
-
- restore(i_state);
-
- if(!istate()) {
- restore(1);
- tputs("\ntimer: ints were off\n\n");
- usflush(Current->output); /* make sure it gets out */
- }
-
- if(!uploadstatus) /* TEST */
- /* Call the functions listed in config.c */
- for(vf = Cfunc;*vf != NULL;vf++)
- (*vf)();
-
- usflush(Current->output); /* Flush current session output */
- pwait(NULL); /* Let them all do their writes */
- flushall(); /* And flush out stdout too */
-
- if(Timers == NULLTIMER)
- continue; /* No active timers, all done */
-
- /* Initialize null expired timer list */
- expired = NULLTIMER;
-
- /* Move expired timers to expired list. Note use of
- * subtraction and comparison to zero rather than the
- * more obvious simple comparison; this avoids
- * problems when the clock count wraps around.
- */
- while(Timers != NULLTIMER && (Clock - Timers->expiration) >= 0){
- if(Timers->next == Timers) {
- printf("\nTimer loop at %lx\n\n",(long)Timers);
- iostop();
- exit(251);
- }
- /* Save Timers since stop_timer will change it */
- t = Timers;
- stop_timer(t);
-
- /* Add to expired timer list */
- if(expired == NULLTIMER){
- expired = t;
- } else {
- for(p = expired ; p->next != NULLTIMER ; p = p->next);
- p->next = t; /* place at end of chain */
- }
- t->next = NULLTIMER;
- }
- /* Now go through the list of expired timers, removing each
- * one and kicking the notify function, if there is one
- * Note that the state should ne TIMER_STOP. We just stopped
- * it remember? Now is someone else changed it, ignore timer.
- */
- while((t = expired) != NULLTIMER){
- expired = t->next;
- if(t->state == TIMER_STOP) {
- t->state = TIMER_EXPIRE;
- if(t->func)
- (*t->func)(t->arg);
- }
- }
- pwait(NULL); /* Let them run before handling more ticks */
- }
- }
-
- /* Start a timer */
- void
- start_timer(struct timer *t)
- {
- struct timer *tnext, *tprev = NULLTIMER;
-
- if(t == NULLTIMER)
- return;
-
- if(t->state == TIMER_RUN)
- stop_timer(t);
-
- if(t->duration == 0)
- return; /* A duration value of 0 disables the timer */
-
- t->expiration = Clock + t->duration;
- t->state = TIMER_RUN;
-
- /* Find right place on list for this guy. Once again, note use
- * of subtraction and comparison with zero rather than direct
- * comparison of expiration times.
- */
- for(tnext = Timers; tnext != NULLTIMER; tprev = tnext, tnext = tnext->next) {
- if((tnext->expiration - t->expiration) >= 0)
- break;
- }
- /* At this point, tprev points to the entry that should go right
- * before us, and tnext points to the entry just after us. Either or
- * both may be null.
- */
- if(tprev == NULLTIMER)
- Timers = t; /* Put at beginning */
- else
- tprev->next = t;
-
- t->next = tnext;
- }
-
- /* Stop a timer */
- void
- stop_timer(struct timer *timer)
- {
- struct timer *t, *tlast = NULLTIMER;
-
- if(timer == NULLTIMER || timer->state != TIMER_RUN)
- return;
-
- /* Verify that timer is really on list */
- for(t = Timers; t != NULLTIMER; tlast = t, t = t->next)
- if(t == timer)
- break;
-
- if(t == NULLTIMER)
- return; /* Should probably panic here */
-
- /* Delete from active timer list */
- if(tlast != NULLTIMER)
- tlast->next = t->next;
- else
- Timers = t->next; /* Was first on list */
-
- t->state = TIMER_STOP;
- }
-
- /* Return millisecs remaining on this timer */
- int32
- read_timer(struct timer *t)
- {
- int32 remaining;
-
- if(t == NULLTIMER || t->state != TIMER_RUN)
- remaining = 0;
- else
- remaining = t->expiration - Clock;
-
- return (remaining <= 0) ? 0 : (remaining * MSPTICK);
- }
-
- void
- set_timer(struct timer *t,int32 interval)
- {
- if(t == NULLTIMER)
- return;
-
- /* Round up small nonzero intervals to one tick */
- t->duration = (interval != 0) ? 1 + (interval + MSPTICK - 1) / MSPTICK : 0;
- }
-
- /* Delay process for specified number of millisecs
- * normally returns 0, if aborted by alarm returning -1 */
- int
- pause(int32 ms)
- {
- int val;
-
- if(Curproc == NULLPROC || ms == 0)
- return 0;
-
- alarm(ms);
-
- /* The actual event doesn't matter, since we'll be alerted */
- while(Curproc->alarm.state == TIMER_RUN) {
- if((val = (int)pwait(Curproc)) != 0)
- break;
- }
- alarm(0L); /* Make sure it's stopped, in case we were killed */
-
- return (val == EALARM) ? 0 : -1;
- }
-
- static void
- t_alarm(void *x)
- {
- alert((struct proc *)x,(void *)EALARM);
- }
-
- /* Send signal to current process after specified number of millisecs */
- void
- alarm(int32 ms)
- {
- if(Curproc != NULLPROC) {
- set_timer(&Curproc->alarm,ms);
- Curproc->alarm.func = t_alarm;
- Curproc->alarm.arg = (char *)Curproc;
- start_timer(&Curproc->alarm);
- }
- }
-
- /* Convert time count in seconds to printable days:hr:min:sec format */
- char *
- tformat(int32 t)
- {
- static char buf[20], *cp;
- unsigned int days, hrs, mins, secs;
- int minus;
-
- if(t < 0) {
- t = -t;
- minus = 1;
- } else
- minus = 0;
-
- secs = (int)(t % 60);
- t /= 60;
- mins = (int)(t % 60);
- t /= 60;
- hrs = (int)(t % 24);
- t /= 24;
- days = (int)(t);
-
- if(minus) {
- cp = buf + 1;
- buf[0] = '-';
- } else
- cp = buf;
-
- sprintf(cp,"%ud:%02uh:%02um:%02us",days,hrs,mins,secs);
-
- return buf;
- }
-